﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Linq;
using System.Text;
using VDS.RDF;
using VDS.RDF.Writing;
using uk.ac.soton.ses.DAL;
using System.Web;
using VDS.RDF.Query;
using VDS.RDF.Query.Datasets;
using VDS.RDF.Parsing;
using VDS.RDF.Writing.Formatting;
using System.Security.Principal;
using System.Collections.Generic;

namespace uk.ac.soton.ses
{
    class Program
    {
        static void Print(IGraph rdfGraph, bool wait)
        {

            RdfXmlWriter xmlwriter = new RdfXmlWriter(0, false);
            xmlwriter.Save(rdfGraph, Console.Out);
            if (wait)
            {
                Console.WriteLine("\n\nPress Enter.");
                Console.ReadLine();
            }
        }
        static void Main(string[] args)
        {
            //We need a graph first
            IGraph rdfGraph = new Graph();
            //g.BaseUri = UriFactory.Create("http://example.org/");
            rdfGraph.NamespaceMap.AddNamespace("dcterms", UriFactory.Create("http://purl.org/dc/terms/"));
            rdfGraph.NamespaceMap.AddNamespace("ore", UriFactory.Create("http://www.openarchives.org/ore/terms/"));
            rdfGraph.NamespaceMap.AddNamespace("hdcparams", UriFactory.Create("https://hdc.soton.ac.uk/params/"));
            rdfGraph.NamespaceMap.AddNamespace("hdcdatasets", UriFactory.Create("https://hdc.soton.ac.uk/_layouts/HDC/ExperimentDetails.aspx?ID="));

            //IUriNode item = rdfGraph.CreateUriNode("hdcparams:item");
            //IBlankNode blank = rdfGraph.CreateBlankNode();
            //IUriNode obj1 = rdfGraph.CreateUriNode("hdcparams:obj1");
            //IUriNode obj2 = rdfGraph.CreateUriNode("hdcparams:obj2");
            //ILiteralNode lit2 = rdfGraph.CreateLiteralNode("LITERAL");
            //ILiteralNode lit1 = rdfGraph.CreateLiteralNode("LIT1");
            //rdfGraph.Assert(new Triple(item, obj1, blank));
            //rdfGraph.Assert(new Triple(blank, obj2, lit1));
            //rdfGraph.Assert(new Triple(blank, obj2, lit2));


            HDCConfigurationOptions hdcconfig = HDCConfiguration.GetConfigurationOptions();
            using (MaterialsMetadataContext dbcontext = new MaterialsMetadataContext(hdcconfig.DatabaseOptions.EntityConnectionString))
            {
                IEnumerable<Experiment> reloadedExperiments =
                        dbcontext.Experiments.Include("ExperimentType").Include("ExperimentParameters").Include("ExperimentChildren").Include("ExperimentCollectionExperimentMaps");

                foreach (Experiment experiment in reloadedExperiments.ToList())
                {
                    IUriNode expNode = rdfGraph.CreateUriNode("hdcdatasets:" + experiment.ID);

                    var expParams = dbcontext.GetExperimentTopLevelParameters(experiment.ID, false);
                    foreach (ExperimentParameter param in expParams)
                    {
                        AddParamNode(dbcontext, rdfGraph, expNode, param);
                    }

                    /*
                    for each tlevel param
                    if parent:create urinode + literal. join urinode to exp. join literal to uri node. go to children
                    if child: create urinode + literal. join urinode to exp. join literal to uri node.
                     * foreach child
                       if parent:create urinode + literal. join urinode to parenturinnode. join literal to this uri node. go to children
                       if child: create urinode + literal. join urinode to parenturinnode. join literal to this uri node.
                    */

                    //foreach (ExperimentParameter param in experiment.ExperimentParameters)
                    //{
                    //    if (!string.IsNullOrEmpty(param.Name) && !string.IsNullOrEmpty(param.Value))
                    //    {
                    //        if (param.Name.Contains(':') || param.Name.Contains(' '))
                    //        {
                    //            continue;
                    //        }
                    //        else
                    //        {
                    //            rdfGraph.Assert(new Triple(expNode, rdfGraph.CreateUriNode("hdcparams:" + param.Name), rdfGraph.CreateLiteralNode(param.Value)));
                    //        }
                    //    }
                    //}
                }
            }


            Print(rdfGraph, true);
            return;

            //THE FOLLOWING IS SPARQL TESTING

            InMemoryDataset ds = new InMemoryDataset(rdfGraph);
            LeviathanQueryProcessor qp = new LeviathanQueryProcessor(ds);

            //First we need an instance of the SparqlQueryParser
            SparqlQueryParser parser = new SparqlQueryParser();

            //Then we can parse a SPARQL string into a query
            SparqlQuery q = parser.ParseFromString(@"
PREFIX xsd:     <http://www.w3.org/2001/XMLSchema#>
PREFIX hdcparams:      <https://hdc.soton.ac.uk/params/>
SELECT * 
WHERE { ?exp hdcparams:het_coding_variants ?val . FILTER (xsd:integer(?val) > 10000) }
");
            object results = qp.ProcessQuery(q);
            if (results is SparqlResultSet)
            {
                SparqlResultSet resultSet = results as SparqlResultSet;
                //Print out the Results
                NTriplesFormatter formatter = new NTriplesFormatter();
                foreach (SparqlResult x in resultSet)
                {
                    Console.WriteLine(x.ToString(formatter));
                }
            }


        }

        private static void AddParamNode(MaterialsMetadataContext dbcontext, IGraph rdfGraph, INode subject, ExperimentParameter param)
        {

            //if (param.Name.Contains(':') || param.Name.Contains(' '))
            //{
            //    return;
            //}

            if (!string.IsNullOrEmpty(param.Name))
            {
                string paramName = param.Name.Replace(':', '_').Replace(' ', '_').Replace('/', '_');
                paramName = HttpUtility.UrlEncode(paramName);

                INode newPredicate = rdfGraph.CreateUriNode("hdcparams:" + paramName);

                //Join the predicate to the value if it exists
                if (!string.IsNullOrEmpty(param.Value))
                {
                    ILiteralNode newLiteralNode = rdfGraph.CreateLiteralNode(param.Value ?? "");
                    rdfGraph.Assert(new Triple(subject, newPredicate, newLiteralNode));
                }

                //Join the predicate to the node returned by the recursion
                List<ExperimentParameter> children = dbcontext.GetExperimentChildParameters(param.ID).ToList();
                if (children.Count() > 0)
                {
                    IBlankNode newBlankNode = rdfGraph.CreateBlankNode();
                    rdfGraph.Assert(new Triple(subject, newPredicate, newBlankNode));

                    foreach (ExperimentParameter childparam in children)
                    {
                        AddParamNode(dbcontext, rdfGraph, newBlankNode, childparam);
                    }
                }
            }
        }
    }
}
